home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / as02.arc / TRIM.ASM < prev    next >
Assembly Source File  |  1985-08-28  |  12KB  |  332 lines

  1.         name    trim
  2.         page    55,132
  3.         title   'TRIM - excerpt lines of a file'
  4. ;
  5. ; TRIM --- excerpts selected columns from each line
  6. ;          of a file and writes them to the selected
  7. ;          output device or file.
  8. ;          
  9. ; A "filter" for MS-DOS or PC-DOS version 2 or higher,
  10. ; after the fashion of Unix.   Reads from the standard input
  11. ; (redirectable) and writes to the standard output (redirectable). 
  12. ; Error messages are directed to the standard error device.  
  13. ;
  14. ; TRIM can be (and usually would be) used in a pipe, e.g.
  15. ;
  16. ;    | TRIM 7,45 |
  17. ;
  18. ; transmits only the characters in columns 7 to 45 (inclusive)
  19. ; of each line.  A minus sign reverses the action, e.g.
  20. ;
  21. ;    | TRIM -7,45 | 
  22. ;
  23. ; transmits all characters except those in columns 7 to 45.
  24. ; Special actions:
  25. ;
  26. ;    | TRIM 0  |        deletes trailing spaces from lines, and
  27. ;    | TRIM -0 |        also discards empty lines
  28. ; By A. K. Head, 6 Duffryn Place, Melbourne, Australia 3142
  29. ; and Ray Duncan, Laboratory Microsystems Inc.
  30. ;
  31.  
  32. command equ     80h             ; buffer for command tail
  33. fcb1    equ     5ch             ; default file control block #1
  34. fcb2    equ     6ch             ; default file control block #2
  35.  
  36. buflen  equ     16384           ; buffer length, alter to taste
  37.  
  38. cr      equ     0dh             ; ASCII carriage return
  39. lf      equ     0ah             ; ASCII line feed
  40. ff      equ     0ch             ; ASCII form feed
  41. eof     equ     01ah            ; End-of-file marker
  42. tab     equ     09h             ; ASCII tab code
  43. blank   equ     20h             ; ASCII blank
  44.  
  45.                                 ; DOS 2.x pre-defined handles
  46. stdin   equ     0000            ; standard input file
  47. stdout  equ     0001            ; standard output file
  48. stderr  equ     0002            ; standard error file
  49. stdaux  equ     0003            ; standard auxilliary file
  50. stdprn  equ     0004            ; standard printer file
  51.  
  52.  
  53. cseg    segment para public 'CODE'
  54.  
  55.         assume  cs:cseg,ds:cseg
  56.  
  57.         org     100H            ; start .COM at 100H
  58.  
  59. start:    jmp     near ptr trim
  60.  
  61. param1  dw      0               ; command parameter #1
  62. param2  dw      0               ; command parameter #2
  63. sign    dw      0               ; nonzero if "-" in command
  64. count   dw      0               ; column count, current line
  65. topin   dw      0               ; chars in input buffer - 1 
  66. char    db      0               ; current character
  67.  
  68. trim    proc    far
  69.  
  70.         xor     si,si           ; initialize buffer pointers
  71.         xor     di,di
  72.         mov     bx,fcb1+1    ; addr of parsed parameter 1
  73.         call    getprm          ; convert it
  74.         cmp     ax,0
  75.         je      trunc        ; zero parameter, go truncate
  76.                 ; trailing blanks etc.
  77.         mov     param1,ax       ; save first parameter
  78.         mov     bx,fcb2+1    ; addr of parsed parameter 2
  79.     cmp    byte ptr [bx],blank ; is it present at all?
  80.     jne    trim0        ; yes, proceed
  81.     jmp    err3        ; no, exit
  82. trim0:    
  83.         call    getprm        ; convert it
  84.         mov     param2,ax       ; save 2nd parameter
  85.         cmp     ax,param1       ; is end column < start column?
  86.         jnb     trim1
  87.         jmp     err3        ; yes, exit with error message
  88.         
  89. trim1:  mov     count,0         ; starting a new line,
  90.                                 ; initialize column counter
  91.  
  92. trim2:  inc     count           ; count characters
  93.         call    cin                ; read a character
  94.     mov    al,char        ; is it carriage return?
  95.     and    al,07fh        ; (ignore high bit in case 
  96.     cmp    al,cr        ;  this is Wordstar file)
  97.         je      trim5        ; yes, found end of line
  98.         mov     ax,count        ; fetch current char count
  99.         cmp     sign,0          ; is this include or exclude call?
  100.         jne     trim4        ; jump, -, exclude range
  101.                                 ; proceed, +, include range
  102.     cmp     ax,param1       ; is column counter within 
  103.                                 ; desired range?
  104.         jb      trim2           ; no, discard this char.
  105.         cmp     ax,param2
  106.         ja      trim2           ; no, discard this char.
  107.  
  108. trim3:    call    cout               ; yes, use this character
  109.         jmp     trim2           ; get next char.
  110.  
  111. trim4:    cmp     ax,param1       ; is column counter outside
  112.                                 ; of excluded range?
  113.         jb      trim3        ; yes, use this character
  114.         cmp     ax,param2
  115.         ja      trim3        ; yes, use this character 
  116.         jmp     trim2           ; no, discard this character
  117.  
  118. trim5:                ; found end of line
  119.         call    cout               ; write carriage return
  120.         call    cin                ; read presumed line feed
  121.         call    cout               ; write line feed
  122.         jmp     trim1
  123.  
  124.  
  125. trunc:                ; come here if zero parameter
  126.                 ; to delete trailing blanks from
  127.                 ; all lines.  If - sign was in
  128.                 ; command parameter, also delete
  129.                 ; empty lines completely.
  130.  
  131. trunc1: mov     count,0         ; initialize column counter
  132.         xor     bp,bp           ; init line pointer
  133.  
  134. trunc2: call    cin                ; read a character
  135.     mov    al,char        ; is it carriage return
  136.     and    al,07fh        ; (ignore high bit in case
  137.         cmp     al,cr             ;  this is Wordstar file) 
  138.         je      trunc3            ; yes, go process end of line
  139.         mov     al,char        ; transfer char. to forming line
  140.         mov     byte ptr ds:[line+bp],al
  141.         inc     bp
  142.         cmp     char,blank      ; is character a space code?
  143.         je      trunc2          ; yes, get next char
  144.         mov     count,bp        ; no, update column count
  145.         jmp     trunc2          ; get next char.
  146.  
  147. trunc3:    xor     bp,bp           ; text string now in LINE
  148.         call    cin                ; discard line feed
  149.         cmp     count,0         ; was line empty?
  150.         jne     trunc4            ; no, go output it
  151.         cmp     sign,0        ; deleting empty lines?
  152.         jne     trunc1          ; yes, discard this one
  153.         jmp     trunc5        ; no, send cr-lf sequence
  154.  
  155. trunc4:                            ; now transfer LINE to BUFOUT
  156.         mov     al,byte ptr ds:[bp+line]
  157.         mov     char,al         ; get next char and
  158.         call    cout               ; send it to output
  159.         inc     bp
  160.         cmp     bp,count        ; entire line sent yet?
  161.         jb      trunc4           ; no, send another char
  162.         
  163. trunc5: mov     char,cr         ; send carriage return
  164.         call    cout
  165.         mov     char,lf         ; and line feed
  166.         call    cout           
  167.         jmp     trunc1
  168.  
  169. exit:   cmp     di,0            ; output buffer empty?
  170.         je      exit1           ; yes
  171.         call    outbuf          ; no, flush it
  172. exit1:  mov     ax,4c00h        ; exit with return code=0
  173.         int     21h             ; if no errors were encountered
  174.  
  175.  
  176. err:                ; print error message and exit.
  177.                 ; DS:DX = addr of message
  178.                 ; CX    = length of message
  179.                 ; AL    = return code
  180.     push    ax        ; save return code
  181.     mov    ah,40h        ; function 40 = write
  182.     mov    bx,stderr    ; handle for error output
  183.     int    21h
  184.     pop    ax        ; retrieve return code
  185.     mov    ah,4ch        ; function 4C = exit
  186.     int    21h
  187.  
  188. err1:    mov     dx,offset err1msg  ; print "output device error" 
  189.         mov     cx,err1len
  190.     mov    al,1        ; return code = 1
  191.     jmp    err
  192.  
  193. err2:    mov     dx,offset err2msg  ; print "disk is full".
  194.         mov     cx,err2len
  195.     mov    al,2        ; return code = 2
  196.     jmp    err
  197.  
  198. err3:    mov     dx,offset err3msg  ; print "bad parameter"
  199.         mov     cx,err3len
  200.     mov    al,3        ; return code = 3
  201.     jmp    err
  202.  
  203. err4:    mov     dx,offset err4msg  ; print "input device error"
  204.         mov     cx,err4len
  205.     mov    al,4        ; return code = 4
  206.     jmp    err
  207.  
  208.  
  209. trim    endp
  210.  
  211.  
  212. cout       proc    near            ; output contents of "char"
  213.                                 ; with autobuffering
  214.         mov     al,char
  215.         mov     byte ptr [di+bufout],al
  216.         inc     di
  217.         cmp     di,buflen       ; buffer full yet?
  218.         jb      cout1
  219.         call    outbuf          ; write buffer
  220. cout1:     ret                     ; back to caller
  221. cout       endp
  222.  
  223.  
  224. outbuf  proc    near            ; write buffer to std output
  225.         mov     ah,40h          ; function 40 = write
  226.         mov     bx,stdout       ; predefined handle 
  227.         mov     cx,di           ; number of characters
  228.         lea     dx,bufout       ; DS:DX = buffer addr
  229.         int     21h             ; request DOS service
  230.         jc      err1        ; jump, device write error
  231.         cmp     ax,di
  232.         jne     err2        ; jump, disk is full
  233.         xor     di,di           ; initialize output buff pointer
  234.         ret                     ; back to caller
  235. outbuf  endp
  236.  
  237.  
  238. cin    proc    near            ; input next char with buffering
  239.         inc     si              ; bump input buffer pointer
  240.         cmp     si,topin        ; buffer exhausted?
  241.         jbe     cin2        ; no, jump
  242.         mov     ah,3fh          ; yes, read some more data
  243.         mov     bx,stdin        ; predefined handle
  244.         mov     cx,buflen       ; max length to read
  245.         lea     dx,bufin        ; DS:DX = input buffer addr
  246.         int     21h             ; request DOS service
  247.         jc      err4        ; jump, input device error
  248.         cmp     ax,0            ; end of file?
  249.     jne    cin1
  250.     jmp    exit            ; yes, goto success exit point
  251. cin1:    dec     ax              ; save offset of top of data
  252.         mov     topin,ax
  253.         xor     si,si           ; zero input buffer pointer
  254. cin2:    mov     al,byte ptr [si+bufin]
  255.         mov     char,al         ; get next char 
  256.         ret
  257. cin    endp
  258.  
  259.  
  260. getprm  proc    near            ; convert numeric parameter to
  261.                                 ; binary and return it in AX
  262.         xor     ax,ax           ; initialize forming answer
  263.         mov     cl,[bx]         ; get first char
  264.         cmp     cl,'-'          ; is it minus sign?
  265.         jne     getp2        ; no, jump
  266.         inc     sign            ; yes, set flag and
  267. getp1:    inc     bx              ; bump command string pointer
  268.                 ; past the "-" sign
  269.         mov     cl,[bx]         ; get next char
  270. getp2:    cmp    cl,'0'        ; at least 1 legal digit?
  271.     jb    getp6        ; no, exit
  272.     cmp    cl,'9'        
  273.     ja    getp6        ; no, exit
  274.     jmp    getp4
  275. getp3:    inc    bx        ; advance through string
  276.     mov    cl,[bx]
  277.     cmp     cl,'0'          ; make sure legal digit 0-9
  278.         jb      getp5        ; not digit, jump
  279.         cmp     cl,'9'
  280.         ja      getp5        ; not digit, jump
  281.         mov     dl,10           ; previous answer * 10
  282.         mul     dl
  283. getp4:    sub     cl,'0'          ; add in the new digit
  284.         xor     ch,ch
  285.         add     ax,cx
  286.         cmp     ah,0            ; new answer > 255?
  287.         je      getp3        ; no, keep converting
  288.         jmp     err3        ; yes, illegal parameter, exit
  289. getp5:    cmp    byte ptr[bx],blank ; if not digit, must be blank
  290.     jne    getp6        ; exit, bad parameter
  291.     ret            ; back to caller
  292. getp6:    jmp    err3        ; ... since too far to reach
  293.                 ; direct with conditional branch
  294. getprm  endp
  295.  
  296.  
  297. err1msg    db      cr,lf
  298.         db      'trim: output device error'
  299.         db      cr,lf
  300. err1len equ     (this byte)-(offset err1msg) 
  301.  
  302. err2msg    db      cr,lf
  303.         db      'trim: disk is full.'
  304.         db      cr,lf
  305. err2len equ     (this byte)-(offset err2msg) 
  306.  
  307. err3msg    db      cr,lf
  308.         db      'trim: bad parameter'
  309.         db      cr,lf
  310. err3len equ     (this byte)-(offset err3msg) 
  311.  
  312. err4msg    db      cr,lf
  313.         db      'trim: input device error'
  314.         db      cr,lf
  315. err4len equ     (this byte)-(offset err4msg) 
  316.  
  317.  
  318. bufin   equ     this byte       ; data is read here
  319.                                 ; from the standard input
  320.  
  321. bufout  equ     bufin+buflen    ; data to be written to
  322.                                 ; standard output is built here
  323.  
  324. line    equ     bufout+buflen   ; temporary line buffer
  325.  
  326.  
  327. cseg    ends
  328.  
  329.         end     start
  330.